﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;

namespace FerrSimplicity
{
    /// <summary>
    /// An abstract class that represents a game state. It provides a location to 
    /// put state specific draw and update code, as well as the ability to suspend
    /// and resume the state.
    /// </summary>
    public abstract class BaseGameState
    {
        #region Fields
        /// <summary>
        /// The game that this state is connected to, useful for loading content and attaching components.
        /// </summary>
        protected Game Game;
        /// <summary>
        /// Storage location for GameComponents while this game state is suspended
        /// </summary>
        List<GameComponent> collection;

        /// <summary>
        /// This variable tells the ManagerGameState to call Update and Draw on this game state
        /// </summary>
        public bool   Active      { get; protected set; }
        /// <summary>
        /// This tells whether or not this game state has already had a call to Initialize. 
        /// </summary>
        public bool   Initialized { get; protected set; }
        #endregion

        #region Constructor
        /// <summary>
        /// Allocates memory, nothing special
        /// </summary>
        /// <param name="aGame">The XNA Game, so we can load content and manipulate the Component list.</param>
        public BaseGameState(Game aGame)
        {
            collection = new List<GameComponent>();
            Game       = aGame;
        }
        #endregion

        #region Virtual Methods
        /// <summary>
        /// This method gets called the first time this game state gets started.
        /// It only gets called once. This method should be overriden, and your
        /// initialization/setup code should go here.
        /// </summary>
        public virtual void Initialize()
        {
            Initialized = true;
        }

        /// <summary>
        /// This will start the state, and dump all stored GameComponents into the 
        /// XNA Game's component list. All other game states should be suspended 
        /// -before- calling this method, or you may find components from other
        /// states stored in the wrong states. The Enabled event should be raised 
        /// with a value of true on all GameComponents in the list
        /// </summary>
        public virtual void Start     ()
        {
            // if not already initialized, intialize!
            if (!Initialized)
                Initialize();

            // dump all of the GameComponents from our list into the Game's list
            for (int i = 0; i < collection.Count; i++)
            {
                Game.Components.Add(collection[i]);
            }
            // enable all of our GameComponents
            for (int i = 0; i < collection.Count; i++)
                collection[i].Enabled = true;

            // clear our list out, so when we suspend, we don't just keep adding stuff on top of our existing GameComponents
            collection.Clear();
            Active = true;
        }

        /// <summary>
        /// Adds all GameComponents currently in the XNA Game's component list into
        /// a collection list (if aSaveComponents is true). It also sets Enabled to false
        /// on all objects, and clears the XNA Game's component list.
        /// </summary>
        public         void Suspend() { Suspend(true); }
        /// <summary>
        /// Adds all GameComponents currently in the XNA Game's component list into
        /// a collection list (if aSaveComponents is true). It also sets Enabled to false
        /// on all objects, and clears the XNA Game's component list.
        /// </summary>
        /// <param name="aSaveComponents">Should suspending save all the components, or are you going to add them all over again on Start? This is a good way to reset a game state.</param>
        public virtual void Suspend(bool aSaveComponents)
        {
            // save all the components in the component list
            if (aSaveComponents)
                foreach (GameComponent com in Game.Components)
                    collection.Add(com);

            // disable and remove all components
            foreach (GameComponent com in Game.Components)
                com.Enabled = false;
            Game.Components.Clear();

            Active = false;
        }

        public virtual void Update (GameTime aTime)
        {
        }

        public virtual void Draw   (GameTime aTime)
        {
        }
        #endregion
    }
}
